home *** CD-ROM | disk | FTP | other *** search
- { The following is an example and discussion of an interrupt routine routine
- written in turbo pascal for use with midi applications on an ibmpcxt with
- a roland mpu401 interface.
- Prior to utilizing the interrupt routines one must
- 1.change the vector address to the offset and code segment of your
- interrupt routine.The address is 4 bytes beginning at 040(decimal)
- -see below routine irq2_on.
- 2.enable irq2 (turn the 2nd byte of port hex 21 to 0 -see irq2_on)
- The routine 'never_call_stop_mode_herc' is an example of
- an irq2 routine which is never called by the program directly -
- rather it is called when an irq2 occurs .The mpu401 sends a irq2
- whenever it wants to send a single byte of information so the routine
- is set up to handle one byte at a time only .
- (This particular routine plays a piano keyboard on the screen in real time
- while also printing notes(no time values) on a piano staff on the screen.
- Other procedures are called which handle these functions.
- The mpu401 has been set to stop mode(command hex 8a)prior to activation
- of these routines,but the shell(inline statements) work the same with
- any mode of the mpu401(ie.record,play,overdub).
- The interrupt routine
- must begin with the inline statement (which saves the current registers)
- and end with the port statement (eoi to irq controller) and another inline
- statement (restore registers).
- In between can be turbo pascal code with the following restrictions
- -as outlined in the turbo manual
- 1.no access to input/output commands such as write or read -
- though can write directly to screen memory.
- 2.only typed constants are allowed -ie variables which have been
- defined initialized to some value.(eg. const mididata :byte=0;
- This is because these variables are stored in the code segment (CS)
- rather than the data segment (DS) which is usually unavailable in
- the interrupt mode.If you really want to access global variables
- you can -according to the turbo manual - store the value of Dseg
- in a constant variable and then use it in the interrupt handler to
- set the ds properly.I have yet to implement this and am not quite
- sure how to (let me know if you have implemented this).
- When finsished with the interrupt mode it is neccessary to disable the
- irq2 (via port hex 21) and restore the old vector for irq2.This is done
- in the routine irq2_off. }
- {****************************************************************************}
- procedure never_call_stop_mode_herc;
-
- begin
- inline ($50/$53/$51/$52/$56/$57/$1E/$06/$fb); {fb=enable further interrupts}
-
- mididata:=port[dataport];
- if mididata<$80 then begin
- c:=c+1;
- if c=3 then begin curr_velocity[user_record_trnum]:=mididata;
- play_herc_lead_sheet
- (curr_running_status[user_record_trnum],
- curr_notenum[user_record_trnum],
- curr_velocity[user_record_trnum]);
- c:=1;end{IF}
- else curr_notenum[user_record_trnum]:=mididata ;end;
- {COULD REDUCE THE IF STATEMENTS }
- if mididata >=$80 then begin
- curr_running_status[user_record_trnum]:=mididata;
- c:=1;end;
-
-
- port[$20]:=$20;
- inline($07/$1f/$5f/$5e/$5a/$59/$5b/$58/$8b/$e5/$5d/$cf); {cf=interrupt return}
- END;
- {****************************************************************************}
- {****************************************************************************}
- procedure init_interrupt(ii:integer);
- {this procedure changes the offset of irq2(=interrupt 10(dec.)) to
- the cseg and offset of the desired interrupt handler }
- begin
- old_ofs:=memw[$0000:ii*4];
- old_seg:=memw[$0000:ii*4+2];
- new_ofs:=ofs(never_call_stop_mode_herc); {was mono}
- new_seg:=cseg;
- memw[$0000:ii*4]:=new_ofs; {change vector address}
- memw[$0000:ii*4+2]:=new_seg;
- writeln('prior vector irq',ii:2,' = $',integerhex(old_seg),
- ':',integerhex(old_ofs));
- write('new vector irq',ii:2,' = $',integerhex(new_seg),
- ':',integerhex(new_ofs));
-
- end;
- {****************************************************************************}
- procedure restore_interrupt(ii:integer);
- begin
- memw[$0000:ii*4]:=old_ofs; {change vector address}
- memw[$0000:ii*4+2]:=old_seg;
- end;
- {****************************************************************************}
- procedure irq2_on;
- begin
- write('enabling irq2');
- write(' port $21 was ',port[$21]);
- init_interrupt(10);
- port[$21]:=($fb and port[$21]); {turns 2nd byte to 0,thus enabling irq2}
- end;
- {****************************************************************************}
- procedure irq2_off;
- begin
- write(' disabling irq2,port $21 was= ',port[$21]);
- port[$21]:= (4 or port[$21]);{turns 2nd byte to 1,thus disabling irq2 }
- restore_interrupt(10);
- end;
- {******************************************}. ... ...-.... 1200 N81N